/**********************************************************
  ToGraph.cpp
  Parsing a standard netlist to a graph file.
  SMART -- Symbolic Moment Analysis for Rapid Timing
  06-08-2008
  (c) Guoyong Shi; SJTU
  09-11-2008
  Zhigang Hao; SJTU
 **********************************************************/


extern "C" {
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h>
#include <assert.h>
}

#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <stdlib.h>
#include "ToGraph.h"

extern int read_input(char *filename);
// Defined in "netgram.g" and duplicated in "netgram.cpp".

//using namespace std;
//extern int SampleNum;
ToGraph::ToGraph()
{

  // Initializations
  NumElems = 0;
  NumNodes = 0;
  NumRess = 0;
  NumCaps = 0;
  NumInds = 0;
  NumSrcs = 0;

  //  NodeTableSize = 1000;
  NodeTableSize = TABLE_SIZE;

  IndexToNode = NULL;

  ElemList = CurElem = NULL;
  CurRes = NULL;
  SrcList = NULL;
  CurSrc = NULL;
  /* NodeTable = (T_NODE**)  \
     malloc(NodeTableSize * sizeof (T_NODE *)); */
  NodeTable = new T_NODE*[NodeTableSize];

  for (int i = 0; i < NodeTableSize; i++)
    NodeTable[i] = NULL;

  SrcNode = NULL;
  GndNode = NULL;
  CTree = NULL;   // root of the C-Tree

#ifdef  TRACE 
  printf("\n[%s : line %d] ToGraph() constructor -- done", __FILE__, __LINE__);
  cout << "\nNodeTableSize = " << NodeTableSize;
  fflush(stdout);
#endif

}

ToGraph::~ToGraph()
{
  // Release the list of elements created.
  while (ElemList)
  {
    CurElem = ElemList;
    ElemList = ElemList->next;
    delete CurElem;
  }
  while (SrcList)
  {
    CurSrc = SrcList;
    SrcList = SrcList->next;
    delete CurSrc;
  }

  Delete_Node_Table();

  Delete_CTree();
  delete CurElem;
  delete CurRes;
  delete SrcNode;
  delete GndNode;
  delete [] IndexToNode;
  delete CurSrc;

}

// Delete the node hash table.
// Code borrowed from XSpice.
void ToGraph::Delete_Node_Table()
{
  T_NODE   *node1, *node2;
  T_ELEM_P *elem_p1, *elem_p2;
  int    i;

#ifdef  TRACE 
  printf("\n[%s : line %d] Delete_Node_Table()", __FILE__, __LINE__);
#endif

  for (i = 0; i < NodeTableSize; i++)
  {
    for (node1 = NodeTable[i]; node1; node1 = node2) { 
      // Delete the list of elemnode pointers
      for (elem_p1 = node1->elem_p; elem_p1; elem_p1 = elem_p2) { 
        // Delete the list of elemnode pointers

        elem_p2 = elem_p1->next; 
        delete (T_ELEM_P*) elem_p1; 
      }
      node2 = node1->next; 
      delete (T_NODE*) node1; 
    } 
  }

  delete [] NodeTable;

#ifdef  TRACE 
  cout << "\nDelete_Node_Table() -- done" << endl;
#endif
}


void ToGraph::Parse_Netlist(char *filename)
{
#ifdef TRACE
  cout << "\nIn Read_Netlist() ";
#endif
  cout << "\n>>>> Parsing netlist ... \n";

  // Call the parser.
  // read_input() defined in the grammar file "netgram.g".
  if (read_input(filename) == -1)
  {
    cerr << "\nMake sure the netlist file exists.";
    exit(1);
  }
  cout << "\n>>>> Finished parsing netlist." << endl;

  // NumRess/NumCaps/NumInds are counted while parsing netlist.
  // Check whether the given circuit satisfies the tree structure requirement.
  // A tree circuit must satisfy:
  //  NumRess == NumCaps

  if (NumRess != NumCaps)
  {
    cout << "\nWarning: The circuit is probably not in tree structure."
      << "\nPlease check the netlist." 
      << endl;
    exit(1);
  }

#ifdef  TRACE 
  printf("\n[%s : line %d] Program runs to here", __FILE__, __LINE__);
  cout << "\nNodeTableSize = " << NodeTableSize;
  fflush(stdout);
#endif

  //Number_Nodes();  // assign numbers to nodes

  Calculate_All_Fanout();

  if (NumCaps > 0) {
    // Create the IndexToNode mapping array
    IndexToNode = new T_NODE*[NumCaps];
  }

}

// Report the netlist statistics after parsing.
void ToGraph::Report_Netlist_Statistics()
{
  cout << "\n\nNetlist statistics: ";
  cout << "\n\tNumber of Elements = " << NumElems;
  cout << "\n\tNumber of Nodes = " << NumNodes;
  cout << "\n\tNumber of Resistors = " << NumRess;
  cout << "\n\tNumber of Capcitors = " << NumCaps;
  cout << "\n\tNumber of Inductors = " << NumInds;
  cout << "\n\tNumber of Sources = " << NumSrcs;
  cout << endl;
}


  void
ToGraph::Parse_RLC(char *name, char *n1, char *n2,
    char *value, char *var_name)
{
  T_NODE *node1, *node2;
  T_ELEM *elem;

#ifdef TRACE
  cout << "\nIn Parse_RLC()";
  cout << "\n\tParsing element [" << name << "]" << flush;
#endif
  /* To decrease the parsing time */
#ifdef CHECK
  elem = Lookup_Element(name);

  if (elem) {
    cout << "\nElement [" << name << "] parsed before. ";
    cout << "This element is skipped.";
    cout << "\n\tPlease check netlist; no duplicated element allowed."
      << endl;
    return;
  }
#endif

  elem = new T_ELEM;
  // I have only 100 chars for elem->name[100].
  strcpy(elem->name, name);
  elem->value[0] = TransValue(value);
  elem->value[1] = elem->value[0];
  Insert_Element(elem);

  node1 = Lookup_Node(n1);

  if ( !node1 )
  {
    node1 = new T_NODE;
    strcpy(node1->name, n1);
    node1->number = -1; // to be numbered
    node1->fanout = 0; // default fanout
    node1->elem_p = NULL;
    if (strcmp(n1, "0") == 0) {
      node1->visited = 1; // no need to visit GND in the future
      GndNode = node1;
    } else {
      node1->visited = 0; // default to "not visited"
    }

    Insert_Node(node1); // insert to hash table
  }

  // No need to build the list of elements connected to the GND.
  if (strcmp(n1, "0") != 0) { 
    Link_Element_To_Node(node1, elem);
  }

  node2 = Lookup_Node(n2);

  if ( !node2 )
  {
    node2 = new T_NODE;
    strcpy(node2->name, n2);
    node2->number = -1; // to be numbered
    node2->fanout = 0; // default fanout
    node2->elem_p = NULL;
    if (strcmp(n2, "0") == 0) {
      node2->visited = 1; // no need to visit GND in the future
      GndNode = node1;
    } else {
      node2->visited = 0; // default to "not visited"
    }

    Insert_Node(node2); // insert to hash table
  }

  // No need to build the list of elements connected to the GND.
  if (strcmp(n2, "0") != 0) { 
    Link_Element_To_Node(node2, elem);
  }

  elem->node1 = node1;
  elem->node2 = node2;

  // Collect element statistics:  
  switch ( tolower(name[0]) )
  {
    case 'r':
      ++NumRess;
      break;
    case 'c':
      ++NumCaps;
      break;
    case 'l':
      ++NumInds;
      break;
    default:
      break;
  }

}


// Code almost the same as Parse_RLC().
  void
ToGraph::Parse_SRC(char *name, char *n1, char *n2, 
        int type, char *val1, char *val2, char *val3,
        char *val4, char *val5, char *val6, char *val7)
{
  char  *value = NULL;
  T_NODE *node1, *node2;
  T_SRC *src;

#ifdef TRACE
  cout << "\nIn Parse_SRC()" << flush;
#endif

  src = new T_SRC;
  // I have only 100 chars for elem->name[100].
  strcpy(src->name, name);
  src->type = type;
  src->para1 = TransValue(val1);
  src->para2 = TransValue(val2);
  src->para3 = TransValue(val3);
  src->para4 = TransValue(val4);
  src->para5 = TransValue(val5);
  src->para6 = TransValue(val6);
  src->para7 = TransValue(val7);

  Insert_Src(src);
  
  node1 = Lookup_Node(n1);

  if ( !node1 )
  {
    node1 = new T_NODE;
    strcpy(node1->name, n1);
    node1->number = -1; // to be numbered
    // Both nodes of the source edge are default to "visited".
    node1->elem_p = NULL;

    Insert_Node(node1); // insert to hash table
  }
  node1->visited = 1; // src node default to "visited"

  node2 = Lookup_Node(n2);

  if ( !node2 )
  {
    node2 = new T_NODE;
    strcpy(node1->name, n2);
    node2->number = -1; // to be numbered
    // Both nodes of the source edge are default to "visited".
    node2->elem_p = NULL;

    Insert_Node(node2); // insert to hash table
  }
  node2->visited = 1; // src node default to "visited"

  // No need to build the list of elements connected to the two nodes.

  src->node1 = node1;
  src->node2 = node2;

  // Get the source node. The SrcNode is the node other than the GND.
  if (strcmp(n1, "0") == 0) {
    SrcNode = node2;
    GndNode = node1;
  } else {
    SrcNode = node1;
    GndNode = node2;
  }

  SrcNode->fanout = 1; // SrcNode always has fanout 1.
} // parseSRC()



//-------- The following methods are private. --------------------------

// Look up a node from the node hash table. 
T_NODE*  ToGraph::Lookup_Node(char *name)
{
  //cout << "\nIn Lookup_Node() ";
  T_NODE  *node;
  int  key;

  // Hash the node table.
  key = hash(name, NodeTableSize);

  // Scan the list linked to the hashed node.
  for (node = NodeTable[key]; node; node = node->next) { 
    if ( strcmp(node->name, name) == 0)  
      return  node; 
  } 

  return NULL;
}

// Look up the capacitance value connected to the given node.
// Note that a capacitor exists between the node (except for source) and GND.
// function may need much time !!!!!!!!!!!!!!!!!
double ToGraph::Lookup_Capacitance(T_NODE *node)
{
  T_ELEM_P *elem_p;
  T_ELEM  *elem;
  double  value = -1;

  for (elem_p = node->elem_p; elem_p; elem_p = elem_p->next)
  {
    // Is this element connected to GND?
    // one node having only one capacitor to gnd
    elem = elem_p->elem;
    if ( elem->node1 == GndNode || elem->node2 == GndNode )
    {
      value = elem->value[0];
    }
  }

  if (value == -1) {
    cout << "\nToGraph::Lookup_Capacitance() : ";
    cout << "No capacitor connected between node ["
      << node->name << "] and GND.";
    cout << "\nPlease check netlist." << endl;

    exit(1); // terminate the program
  } else {
    return  value;
  }
}


// Look up the capacitor connected to the given node.
// Note that a capacitor exists between the node (except for source) and GND.
T_ELEM* ToGraph::Lookup_Capacitor(T_NODE *node)
{
  T_ELEM_P *elem_p;
  T_ELEM  *elem;
  T_ELEM  *elemC = NULL;

  for (elem_p = node->elem_p; elem_p; elem_p = elem_p->next)
  {
    // Whether is one end of the element GND?
    elem = elem_p->elem;
    if ( elem->node1 == GndNode || elem->node2 == GndNode )
    {
      elemC = elem;
    }
  }

  if ( !elemC ) {
    cout << "\nToGraph::Lookup_Capacitance() : ";
    cout << "No capacitor connected between node ["
      << node->name << "] and ground.";
    cout << "\nPlease check netlist." << endl;
  } else {
    return  elemC;
  }
}

// Look up the inductor connected to the given node.
T_ELEM* ToGraph::Lookup_Inductor(T_NODE *node)
{
  T_ELEM_P *elem_p;
  T_ELEM  *elem;
  T_ELEM  *elemL = NULL;

  for (elem_p = node->elem_p; elem_p; elem_p = elem_p->next)
  {
    elem = elem_p->elem;
    if ( tolower(elem->name[0]) == 'l' )
    {
      elemL = elem;
    }
  }

  if ( !elemL ) {
    cout << "\nToGraph::Lookup_Inductor() : ";
    cout << "No inductor connected to node ["
      << node->name << "].";
    cout << "\nPlease check netlist." << endl;
  } else {
    return  elemL;
  }
}
// Calculate the fanout of all nodes.
// Note that a node fanout = count of connected edges - 2; 
// two edges subtracted are: the one connecting backward and 
// the one connecting to GND.
void ToGraph::Calculate_All_Fanout()
{
  int   fanout;
  T_NODE   *node;
  T_ELEM_P *elem_p;

#ifdef  TRACE 
  printf("\n[%s : line %d] Calculate_All_Fanout()", __FILE__, __LINE__);
#endif

  for (int i = 0; i < NodeTableSize; i++)
  {
    for (node = NodeTable[i]; node; node = node->next) { 
      fanout = 0;
      for (elem_p = node->elem_p; elem_p; elem_p = elem_p->next) { 
        ++fanout; 
      }
      node->fanout = fanout - 2; // excluding C and its parent
      // only work on one tree parent case !!!!!!!!!!!!!!
    } 
  }

#ifdef  TRACE 
  printf("\n[%s : line %d] Calculate_All_Fanout() -- done", __FILE__, __LINE__);
  fflush(stdout);
#endif
}
// time consuming !!!!!!!!!!!!!!!!!!!!!!!!!
// Look up an element from the edge list.
T_ELEM* ToGraph::Lookup_Element(char *elem_name)
{
  T_ELEM  *elem;

  //cout << "\nIn Lookup_Edge() ";
  if (!elem_name)  return NULL;

  for (elem = ElemList; elem; elem = elem->next) {
    if ( strcmp(elem->name, elem_name) == 0)  
      return elem;
  }
  
  return NULL;
}


// Inserts a new node to the node hash table. 
// The node is always inserted at the head of the hashed node list.
// The total number of nodes is counted here.
void ToGraph::Insert_Node(T_NODE *node)
{
  int    key; 

#ifdef TRACE
  cout << "\nToGraph::Insert_Node()";
  //cout << "\nNodeTableSize = " << NodeTableSize;
#endif

  key = hash(node->name, NodeTableSize); 

  // Insert at the head of node table list (hashed).
  // Insert in a reverse order, that is newly inserted node would on top
  // Good algorithm because usually needed node is just recently inserted.
  node->next = NodeTable[key]; 
  NodeTable[key] = node; 

  ++NumNodes;

#ifdef TRACE
  cout << "\nNode \"" << node->name << "\" inserted to the Node Table.";
  //cout << "\nNodeTableSize = " << NodeTableSize;
  cout << endl;
#endif
}


// Insert an element at the head of the element list.
// The total number of elements is counted here.
void ToGraph::Insert_Element(T_ELEM *elem)
{
#ifdef TRACE
  cout << "\nIn Insert_Element() ";
#endif

  elem->next = ElemList;
  ElemList = elem;

  ++NumElems;

#ifdef TRACE
  cout << "\nInserted element [" << elem->name << "]" << endl;
#endif
}

// Insert a source at the head of the source list.
// The total number of srcs is counted here.
void ToGraph::Insert_Src(T_SRC *src)
{
#ifdef TRACE
  cout << "\nIn Insert_Src() ";
#endif

  src->next = SrcList;
  SrcList = src;

  ++NumSrcs;

#ifdef TRACE
  cout << "\nInserted src [" << src->name << "]" << endl;
#endif
}

void ToGraph::Print_All_Elements()
{
  T_ELEM  *elem;

  cout << "\n\nList of elements:";

  for (elem = ElemList; elem; elem = elem->next) {
    printf("\n\t%s --- [%s] --- [%s]", elem->name, 
        elem->node1->name, elem->node2->name);
  }
  cout << endl;
}

// Print all nodes and fanout elements.
void ToGraph::Print_All_Nodes()
{
  T_NODE   *node;
  T_ELEM_P *elem_p;
  int    i;

  cout << "\n\nList of nodes:";

  for (i = 0; i < NodeTableSize; i++)
  {
    for (node = NodeTable[i]; node; node = node->next) { 
      printf("\n\tnode \"%s\" (#%d) -- (%s) ", node->name,
          node->number,
          node->visited ? "visited" : "not visited");
      for (elem_p = node->elem_p; elem_p; elem_p = elem_p->next) { 
        printf("\n\t\t-- [%s]", elem_p->elem->name);
      }
    } 
  }
  cout << endl; 
}


// Add an element pointer to the list of elements connected to the node.
  void 
ToGraph::Link_Element_To_Node(T_NODE *node, T_ELEM *elem)
{
  T_ELEM_P *elem_p = new T_ELEM_P;
  elem_p->elem = elem;

#ifdef BACKWARDORDER
  /* add element in backward order eg. R10->C3->L3 */
  elem_p->next = node->elem_p;
  node->elem_p = elem_p;
#else
  T_ELEM_P *elem_tmp;
  if (node->elem_p != NULL) {
    elem_tmp = node->elem_p;
    while (elem_tmp->next != NULL) {
      elem_tmp = elem_tmp->next;
    }
    elem_tmp->next = elem_p;
    elem_p->next = NULL;
  } else {
    node->elem_p = elem_p;
    elem_p->next = NULL;
  }
#endif

}


// Assign an integer number to each node.
// Note that the node names in the netlist are treated as strings,
// even they are numbered.
// According to the netlist standard, the ground node is always 
// named "0" and will also be numbered 0.
//
// Warning: This function numbers the nodes in the order of
//  nodes in the Node Table. However, for this project
//  we shall use the node numbers to locate the moment
//   in a moment array. Hence, the nodes must be numbered
//  in a special way. This is done when we create the C-Tree.
//
void ToGraph::Number_Nodes()
{
#ifdef  TRACE
  cout << "\nIn Number_Nodes() ";
#endif

  if (!NodeTable)  return;  // do nothing

  T_NODE  *node;
  int  cnt = 1;

#ifdef  TRACE 
  printf("\n[%s : line %d] Program runs to here", __FILE__, __LINE__);
  cout << "\nNodeTableSize = " << NodeTableSize;
  fflush(stdout);
#endif

  for (int i = 0; i < NodeTableSize; i++)
  {
    for (node = NodeTable[i]; node; node = node->next) { 
      if (!node) {
        cout << "\nSomething is wrong with the Node Table." << endl;
        exit(1);
      }
      if (strcmp(node->name, "0") == 0)
        node->number = 0;
      else
        node->number = cnt++;
    } 
  }

  // Set the number of nodes
  // NumNodes = cnt;  // already added by 1
  // Number of nodes has been counted during parsing.

#ifdef  TRACE
  cout << "\nNumber_Nodes() -- done " << endl;
#endif
}

T_NODE* ToGraph::Get_Node_By_Index(int k)
{
  if (!IndexToNode || k >= NumCaps)
    return NULL;
  else
    return IndexToNode[k];
}


// Creates a Capacitor tree (C-Tree) that has the same topology as the original 
// tree circuit.
// The C-Tree is created via traversing the circuit graph represented by
// T_NODEs and T_ELEMs.
// It starts from the source node saved in [T_NODE *SrcNode]. 
// The root node of the C-Tree is saved in [C_NODE *CTree].

void ToGraph::Create_CTree()
{
  T_NODE *node;
  T_ELEM  *elem;

#ifdef  TRACE
  cout << "\nToGraph::Create_CTree()";
#endif

  if ( !SrcNode ) {
    cout << "\nCreate_CTree() : No source node is found. ";
    cout << "No C-Tree is created." << endl;
    return; 
  }

  // Get the first node (root) connected to SrcNode.
  elem = SrcNode->elem_p->elem;
  if (elem->node1 == SrcNode ) {
    node = elem->node2;
  } else {
    node = elem->node1;
  } 
  CurRes = elem; // need to know the current driving resistor
  // cout << RAND_MAX << endl;
  // used for debug
  /*
     for (int i=0; i<=MONTECARLO_SAMPLE; i++) {
     cout << elem->value[i] << endl;
     }
     */
  // Start recursive construction starting from node1.
  Create_CTree_r(node, CTree);

}
// Find the inductor if the circuit is RLC circuit
// return the other node of the L element.
T_NODE* ToGraph::Lookup_Ind_Node(T_NODE *node)
{
  T_ELEM_P *elem_p;
  T_ELEM  *elem;
  double  value = -1;

  for (elem_p = node->elem_p; elem_p; elem_p = elem_p->next)
  {
    elem = elem_p->elem;
    if (tolower(elem->name[0]) == 'l') {
      if (elem->node1 == node)
        return elem->node2;
      else
        return elem->node1;
    }
  }
  cout << "\nToGraph::Lookup_Ind_Node() : ";
  cout << "No inductor connected to node ["
    << node->name << "].";
  cout << "\nPlease check netlist." << endl;

  exit(1); // terminate the program
}

// Recursively construct the C-Tree from the circuit root node passed in.
// This implementation is "Depth-First".
// While a C-Tree is created, all nodes (except for GND and SRC)
// are numbered in the Depth-First order.
void ToGraph::Create_CTree_r(T_NODE *node, C_NODE *&ctree)
{
  T_ELEM   *elem;
  T_ELEM_P  *elem_p;
  T_NODE *node_tmp;
  int   n = 0;
  static int  k = 0;  
  // k numbers the circuit nodes as well as the C_NODE's.
  // k is also the index of moments.

#ifdef TRACE
  printf("\nCreate_CTree_r() -- node [%s]", node->name);
#endif
  // Check if it is RLC circuit
  if (NumInds > 0)
    node_tmp = Lookup_Ind_Node(node);
  else
    node_tmp = node;

  // Mark the node "visited"
  node_tmp->visited = 1;
  node_tmp->number = k;  // assign node number in preorder

  // Save the mapping from node index to node
  IndexToNode[k] = node_tmp;

  // Create a C-Tree node.
  ctree = new C_NODE;
  ctree->number = k++;  // C_NODE number is equal to ckt node #.
  //ctree->Cap = Lookup_Capacitance(node_tmp); 

  // Temporarily used for debugging ...
  ctree->elemC = Lookup_Capacitor(node_tmp);
  if (NumInds > 0)
    ctree->elemL = Lookup_Inductor(node_tmp);
  else
    ctree->elemL = NULL;
  ctree->elemR = CurRes; // Keep the driving resistor
  ctree->fanout = node_tmp->fanout;

  ctree->SumHigherOrder = ctree->elemC->value[1];  // initial Sum
  ctree->SumLowerOrder = 0;
  // moment will be substituted when calculating high-order moments.

#ifdef TRACE
  printf("\n    Created C-Tree node [%s]", ctree->elemC->name);
#endif

  // Create space for children C_NODEs
  if (node_tmp->fanout > 0) {
    ctree->child = new C_NODE*[node_tmp->fanout];
  } else {
    ctree->child = NULL;
    //ctree = NULL;
    return;
  }

  // Traverse the list of elements connected to the node.
  elem_p = node_tmp->elem_p;
  for (;  elem_p;  elem_p = elem_p->next )
  {
    elem = elem_p->elem;
    // Recur only for a node not visited yet.
    if ( tolower(elem->name[0]) == 'l' ) {
      continue; // incase it is L
    } else if ( !elem->node1->visited ) {
      node_tmp = elem->node1;
    } else if ( !elem->node2->visited ) {
      node_tmp = elem->node2;
    } else {
      continue;  // both nodes are visited
    }
#ifdef TRACE
    printf("\n... Recur on node [%s]",  node_tmp->name);
#endif
    CurRes = elem;
    Create_CTree_r(node_tmp, ctree->child[n++]); //depth first algorithm
  }
  ctree->fanout = n;
}


void ToGraph::Print_CTree()
{
  cout << "\n\nPrinting C-Tree: ";

  if (!CTree) {
    cout << "\n............ C-Tree is empty.";
  } else {
    Print_CTree_r(CTree);
  }
  cout << endl << endl;
}

// Recursively print the C-Tree.
void ToGraph::Print_CTree_r(C_NODE *ctree)
{
  static int layer = 0; // control printing indent

  if ( ctree == NULL )  // reached a leaf
    return; 

  ++layer;
  cout << endl;
  for (int i = 0; i < layer; i++)  cout << "    ";

  printf("%s (%g) [%s]", ctree->elemC->name, 
      ctree->SumHigherOrder, ctree->elemR->name);

  for (int n = 0;  n < ctree->fanout; n++)
  {
    Print_CTree_r(ctree->child[n]);
  }

  --layer;
}

// Let node Ci hold the sum of all Cj's (including Ci) in the subtree rooted at Ci.
// The previously calculated moments ((j-1)th order) are used if necessary.
// (Ci*m[i, j-1]) is evaluated and accumulated.
void ToGraph::Evaluate_CTree(double *moment)
{
  Evaluate_CTree_r(CTree, moment);
}


// Recursively evaluate the C-Tree in post-order.
// The 0th order moment could be initialized to all "1". 
// But to avoid multiplication by "1", we pass in NULL for moment-0.
void ToGraph::Evaluate_CTree_r(C_NODE *ctree, double *moment)
{
  double  sum;

  if ( ctree == NULL )  // reached a leaf
    return; 

  if (moment == NULL) {
    sum = ctree->elemC->value[1]; // for 1st order moment
  } else {
    sum = ctree->elemC->value[1] * moment[ctree->number];
  }

  for (int n = 0;  n < ctree->fanout; n++)
  {
    Evaluate_CTree_r(ctree->child[n], moment);

    if(ctree->child[n]) {
      sum += ctree->child[n]->SumHigherOrder;
      /* if (moment == NULL) {
         sum += ctree->child[n]->Cap;
         } else {
         sum += (ctree->child[n]->Cap) * moment[k];
         } */
    }
  }
  if (moment == NULL)
    ctree->SumLowerOrder = 0;
  else
    ctree->SumLowerOrder = ctree->SumHigherOrder;
  ctree->SumHigherOrder = sum;
}

void ToGraph::Delete_CTree()
{ 
  Delete_CTree_r(CTree);  
}


// Recursively release the C-Tree.
void ToGraph::Delete_CTree_r(C_NODE *ctree)
{
  if ( ctree == NULL ) // reached a leaf
    return;

  for (int n = 0;  n < ctree->fanout; n++)
  {
    Delete_CTree_r(ctree->child[n]);
    delete (C_NODE *)  ctree->child[n];
  }
}


// A hash function for fast locating entries in a hash table.
int ToGraph::hash(char *name,  int tsize)
{
  char *s; 
  register int i = 0; 

  // In case a NULL string.
  if (!name) return (0);

  for (s = name; *s; s++) {
    i += (unsigned) *s; 
  }

  return (i % tsize);
}

void ToGraph::Get_Sample_Value(T_ELEM *elem, int num, double ratio)
{
  elem->value[num] = elem->value[0] * ratio;
}

void ToGraph::Generate_Sample()
{
  T_ELEM *elem;
  int i;
  double ratio;
  for (elem = Get_Elem_List(); elem; elem = elem->next) {
    //for (i = 1; i <= MONTECARLO_SAMPLE; i++) {
    //ratio = (2*(double)rand()/((double)RAND_MAX+1)-1)*VARIATION + 1;
    ratio = (2*(double)rand()/((double)RAND_MAX)-1)*VARIATION + 1;
    //cout << ratio << endl;
    Get_Sample_Value(elem, 1, ratio);
    //}

  }
}
/* ifstream version
void ToGraph::Get_Hspice_Sample()
{
  T_ELEM *elem;
  string readin;
  //stringstream temp;
  double value;
  int i;
  //int j;
  ifstream infile("rlc_tree1000_hspice_mc_var10_sample1000.out",ios::in);
  if (!infile)
  {
    cerr<<"file could not be opened."<<endl;
    exit(0);
  } 

  for (elem = Get_Elem_List()->next; elem; elem = elem->next) {
    //j = 0;
    for (i = 1; i <= 1000; i++) {
      getline(infile, readin);
      value = atof(readin.c_str());
      //cout << value <<endl;
      Set_Sample_Value(value, elem, i);
    }
  }
}
*/
void ToGraph::Get_Hspice_Sample(ifstream &infile)
{
  T_ELEM *elem;
  //istringstream readin;
  string readin;
  //string dump;
  //stringstream temp;
  double value;
  int i;
  //int j;

  //for (elem = Get_Elem_List()->next; elem; elem = elem->next) {
  for (elem = Get_Elem_List(); elem; elem = elem->next) {// Without Src
    //j = 0;
      getline(infile, readin);
      istringstream stream(readin);
      stream >> value;
      //value = atof(readin.c_str());
      //cout << value << endl;
      Set_Sample_Value(value, elem, 1);
  }
}

void ToGraph::Set_Sample_Value(double val, T_ELEM *elem, int cnt)
{

  elem->value[cnt] = val;

}
